package com.songlanyun.modules.coupon.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.songlanyun.common.enums.CouponConstant;
import com.songlanyun.common.exception.RRException;
import com.songlanyun.common.utils.DateUtils;
import com.songlanyun.common.utils.custom.ClassConvertUtils;
import com.songlanyun.modules.coupon.entity.CouponEntity;
import com.songlanyun.modules.coupon.model.dto.CouponPageReq;
import com.songlanyun.modules.coupon.model.dto.CouponReceivePageReq;
import com.songlanyun.modules.coupon.model.vo.CouponEntityVo;
import com.songlanyun.modules.coupon.model.vo.CouponReceiveRecordVo;
import com.songlanyun.modules.coupon.service.CouponReceiveRecordUseService;
import com.songlanyun.modules.coupon.service.CouponService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songlanyun.common.utils.PageUtils;
import com.songlanyun.common.utils.Query;

import com.songlanyun.modules.coupon.dao.CouponReceiveRecordDao;
import com.songlanyun.modules.coupon.entity.CouponReceiveRecordEntity;
import com.songlanyun.modules.coupon.service.CouponReceiveRecordService;
import org.springframework.transaction.annotation.Transactional;


@Service("couponReceiveRecordService")
public class CouponReceiveRecordServiceImpl extends ServiceImpl<CouponReceiveRecordDao, CouponReceiveRecordEntity> implements CouponReceiveRecordService {

    @Autowired
    private CouponService couponService;

    @Autowired
    private CouponReceiveRecordUseService couponReceiveRecordUseService;


    @Override
    public CouponReceiveRecordEntity create(CouponReceiveRecordEntity entity){
        this.baseMapper.insert(entity);
        return entity;
    }

    @Override
    public CouponReceiveRecordEntity modify(CouponReceiveRecordEntity entity) {
        return null;
    }

    @Override
    public void remove(Long id) {

    }

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CouponReceiveRecordVo> page = this.baseMapper.queryCouponPage(new Query<CouponReceiveRecordVo>().getPage(params), paramsMapToReq(params));
        page.getRecords().forEach(CouponReceiveRecordVo::loadOrderCodes);
        return new PageUtils(page);
    }

    private CouponReceivePageReq paramsMapToReq(Map<String, Object> params)
    {
        CouponReceivePageReq req = new CouponReceivePageReq();
        String userId = MapUtil.getStr(params, "user_id");
        if (StringUtils.isNotEmpty(userId)) {
            req.setUserId(ClassConvertUtils.objToLong(userId));
        }
        String couponId = MapUtil.getStr(params, "coupon_id");
        if (StringUtils.isNotEmpty(couponId)) {
            req.setCouponId(ClassConvertUtils.objToLong(couponId));
        }

        Integer status = MapUtil.getInt(params, "status");
        if (!ObjectUtils.isNull(status) && status>=-1) {
            req.setStatus(status);
        }

        Date startTime = MapUtil.getDate(params, "start_time");
        if (!ObjectUtils.isNull(startTime)) {
            req.setStartTime(startTime);
        }

        Date endTime = MapUtil.getDate(params, "end_time");
        if (!ObjectUtils.isNull(endTime)) {
            req.setEndTime(endTime);
        }

        String mobile = MapUtil.getStr(params, "mobile");
        if (StringUtils.isNotEmpty(mobile)) {
            req.setMobile(mobile);
        }


        if(!ObjectUtils.isNull(req.getStartTime()) && !ObjectUtils.isNull(req.getEndTime()))
        {
            if(DateUtil.compare(req.getStartTime(),req.getEndTime())>=0)
            {
                throw new RRException("开始时间必须小于结束时间");
            }
        }
        return req;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void receive(Long userId, Long couponId) {
        CouponEntity coupon = couponService.loadById(couponId, true);
        if(coupon.canReceive(1) < 0)
        {
            throw new RRException("当前优惠券已不能领取");
        }

        Integer noUsedNum = this.userReceiveNoUsedCount(userId,couponId);
        if(coupon.getReceiveLimit()>0) {
            if (noUsedNum >= coupon.getReceiveLimit()) {
                throw new RRException("您已超出了限领的张数");
            }
        }

        if(!CouponConstant.CouponStatus.RELEASED.equals(coupon.getStatus()))
        {
            throw new RRException("优惠券活动还没有开发或已停止");
        }

        receiveCoupon(userId, coupon);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void give(Long userId,  String couponCode,boolean tw) {
        CouponEntity coupon = couponService.loadByCode(couponCode, false);
        if(ObjectUtil.isNull(coupon))
        {
            if(tw)
            {
                throw new RRException("当前优惠券已不能领取");
            }
            return;

        }
        if( coupon.canReceive(1) < 0)
        {
            if(tw)
            {
                throw new RRException("当前优惠券已不能领取");
            }
            return;

        }

        Integer noUsedNum = this.userReceiveNoUsedCount(userId,coupon.getId());
        if(coupon.getReceiveLimit()>0 && noUsedNum>=coupon.getReceiveLimit())
        {
            if(tw)
            {
                throw new RRException("您已超出了限领的张数");
            }
            return;

        }

        if(!CouponConstant.CouponStatus.RELEASED.equals(coupon.getStatus()))
        {
            if(tw)
            {
                throw new RRException("优惠券活动还没有开发或已停止");
            }
            return;
        }

        receiveCoupon(userId,  coupon);
    }

    private void receiveCoupon(Long userId, CouponEntity coupon) {
        CouponReceiveRecordEntity record = new CouponReceiveRecordEntity();
        record.setCouponId(coupon.getId());
        record.setUserId(userId);
        Date now = new Date();
        Date expireTime = DateUtils.addDateDays(now, coupon.getExpiredDay());
        record.setReceiveTime(now);
        record.setUseStatus(false);
        record.setExpireTime(expireTime);
        this.create(record);

        coupon.setReceiveNum(coupon.getReceiveNum() + 1);
        if (coupon.getIssueNumber() != -1) {
            if (coupon.getIssueNumber() - coupon.getReceiveNum() <= 0) {
                coupon.setStatus(CouponConstant.CouponStatus.STOP);
            }
        }

        couponService.modify(coupon);
    }

    /**
     * 查出我领取的店铺券,
     * 1、对应的店铺，
     * 2、店铺券，
     * 3、可以使用的，
     * 4、按面额排倒倒叙面额大的排前面，
     * 5、按门槛值排正序，门槛低的排前面，
     * 6、按通用券排正序，通用券排进面
     */
    @Override
    public List<CouponReceiveRecordVo> loadMyShopCoupons(Long userId, Long shopId) {
        return this.baseMapper.loadMyShopCoupons(userId,shopId);
    }

    @Override
    public CouponReceiveRecordEntity loadMyCoupon(Long userId, Long id) {
        return this.baseMapper.selectOne(new LambdaQueryWrapper<CouponReceiveRecordEntity>()
        .eq(CouponReceiveRecordEntity::getId,id)
        .eq(CouponReceiveRecordEntity::getUserId,userId)
        .last("limit 1"));
    }

    /**
     * 查出我领取的平台券,
     * 1、可以使用的，
     * 2、按面额排倒倒叙面额大的排前面，
     * 3、按门槛值排正序，门槛低的排前面，
     * 4、按通用券排正序，通用券排进面
     */
    @Override
    public List<CouponReceiveRecordVo> loadMyPlatCoupons(Long userId) {
        return this.baseMapper.loadMyPlatCoupons(userId);
    }

    @Override
    public void useCoupon(Long userId, Long myCouponId, Long orderId, String orderCode, BigDecimal couponResultValue) {
        CouponReceiveRecordEntity couponReceiveRecordEntity = this.loadMyCoupon(userId, myCouponId);
        if(!ObjectUtils.isNull(couponReceiveRecordEntity))
        {
            couponReceiveRecordEntity.setUseStatus(true);
            couponReceiveRecordEntity.setUseTime(new Date());
            this.baseMapper.updateById(couponReceiveRecordEntity);
            couponReceiveRecordUseService.recordOrder(couponReceiveRecordEntity.getId(),orderId,orderCode,couponResultValue);
        }

    }

    @Override
    public void newPersonCoupon(Long userId) {
        List<CouponEntity> couponEntities = couponService.loadValidNewPerson();
        couponEntities.forEach(c->{
            receiveCoupon(userId,c);
        });
    }

    @Override
    public CouponReceiveRecordVo loadByCouponSlimEntity(Long myCouponId, Boolean tw) {
        CouponReceiveRecordVo vo  = this.baseMapper.loadByCouponSlimEntity(myCouponId);
        if(tw && ObjectUtil.isNull(vo))
        {
            throw new RRException("不存在领取的优惠券");
        }
        return vo;
    }

    public Integer userReceiveNoUsedCount(Long userId, Long couponId) {
        return this.count(new LambdaQueryWrapper<CouponReceiveRecordEntity>()
        .eq(CouponReceiveRecordEntity::getUserId,userId)
        .eq(CouponReceiveRecordEntity::getCouponId,couponId)
        .eq(CouponReceiveRecordEntity::getUseStatus,false));
    }

}
